package articles_api

import (
	"gin_study_blog/common"
	"gin_study_blog/common/blog_type"
	"gin_study_blog/common/http"
	"gin_study_blog/models"
	"gin_study_blog/utils"
	md "github.com/JohannesKaufmann/html-to-markdown"
	"github.com/PuerkitoBio/goquery"
	"github.com/gin-gonic/gin"
	"github.com/russross/blackfriday"
	"math/rand"
	"strings"
	"time"
)

type ArticleModel struct {
	Title        string          `json:"title" binding:"required" msg:"请输入文章标题"`    // 文章标题
	Introduction string          `json:"introduction"`                              // 文章简介
	Content      string          `json:"content"`                                   // 文章内容
	Category     string          `json:"category" binding:"required" msg:"请输入文章分类"` // 文章分类
	Source       string          `json:"source"`                                    // 文章来源
	Link         string          `json:"link"`                                      // 原文链接
	BannerID     uint            `json:"banner_id"`                                 // 封面id
	Tags         blog_type.Array `json:"tags"`                                      // 文章标签
}

func (ArticlesApi) ArticlesCreateView(c *gin.Context) {
	var cr ArticleModel
	err := c.ShouldBindJSON(&cr)
	if err != nil {
		http.FailWithError(err, &cr, c)
		return
	}
	_claims, _ := c.Get("user")
	claims := _claims.(*utils.UserClaims)
	userID := claims.UserID
	userNickName := claims.NickName

	// 校验content xss

	// 处理 content
	unsafe := blackfriday.MarkdownCommon([]byte(cr.Content))
	// 是否存在 script 标签
	doc, _ := goquery.NewDocumentFromReader(strings.NewReader(string(unsafe)))
	// 查找是否存在 script 标签
	nodes := doc.Find("script").Nodes
	if len(nodes) > 0 {
		// 存在 script 标签
		doc.Find("script").Remove()
		converter := md.NewConverter("", true, nil)
		html, _ := doc.Html()
		markdown, _ := converter.ConvertString(html)
		cr.Content = markdown
	}
	// 如果简介为空, 就是用文章里面的内容作为简介
	if cr.Introduction == "" {
		// 汉字的截取
		abs := []rune(doc.Text())
		if len(abs) > 100 {
			cr.Introduction = string(abs[:100])
		} else {
			cr.Introduction = string(abs)
		}
	}
	// 不传 banner_id, 就在后台随机选一张
	if cr.BannerID == 0 {
		var bannerList []uint
		err = common.DB.Model(models.BannerModel{}).Select("id").Scan(&bannerList).Error
		if err != nil {
			http.FailWithMessage("请上传封面图", c)
			return
		}
		// 随机取一个值
		rand.Seed(time.Now().UnixNano())
		cr.BannerID = bannerList[rand.Intn(len(bannerList))]
	}
	// 查询 banner
	var bannerUrl string
	err = common.DB.Model(models.BannerModel{}).Where("id = ?", cr.BannerID).Select("path").Scan(&bannerUrl).Error
	if err != nil {
		common.Log.Error(err.Error())
		http.FailWithMessage("图片不存在", c)
		return
	}

	// 查询用户头像
	var avatar string
	err = common.DB.Model(models.UserModel{}).Where("id = ?", userID).Select("avatar").Scan(&avatar).Error
	if err != nil {
		common.Log.Error(err.Error())
		http.FailWithMessage("用户不存在", c)
		return
	}

	// 添加索引
	now := time.Now().Format("2006-01-02 15:04:05")
	articleData := &models.ArticleModel{
		CreatedAt:    now,
		UpdatedAt:    now,
		Title:        cr.Title,
		Keywords:     cr.Title,
		Introduction: cr.Introduction,
		Content:      cr.Content,
		UserID:       userID,
		UserNickName: userNickName,
		UserAvatar:   avatar,
		Category:     cr.Category,
		Source:       cr.Source,
		Link:         cr.Link,
		BannerID:     cr.BannerID,
		BannerUrl:    bannerUrl,
		Tags:         cr.Tags,
	}
	err = articleData.Create()
	if err != nil {
		common.Log.Error(err.Error())
		http.FailWithMessage("发布文章失败", c)
		return
	}
	// 使用异步
	go utils.AsyncArticleByFullText(articleData.ID, articleData.Title, articleData.Content)
	http.IsOkWithMessage("发布文章成功", c)
}
